<script lang="tsx">
  import {compile, computed, defineComponent, h, ref} from 'vue';
  import {useI18n} from 'vue-i18n';
  import type {RouteMeta} from 'vue-router';
  import {RouteRecordRaw, useRoute, useRouter} from 'vue-router';
  import {useAppStore} from '@/store';
  import {listenerRouteChange} from '@/utils/route-listener';
  import {openWindow, regexUrl} from '@/utils';
  import useMenuTree from './use-menu-tree';

  export default defineComponent({
    emit: ['collapse'],
    setup() {
      const {t} = useI18n();
      const appStore = useAppStore();
      const router = useRouter();
      const route = useRoute();
      const {menuTree} = useMenuTree();
      const collapsed = computed({
        get() {
          if (appStore.device === 'desktop') return appStore.menuCollapse;
          return false;
        },
        set(value: boolean) {
          appStore.updateSettings({menuCollapse: value});
        },
      });

      const openKeys = ref<string[]>([]);
      const selectedKey = ref<string[]>([]);

      const goto = (item: RouteRecordRaw) => {
        // Open external link
        if (regexUrl.test(item.path)) {
          openWindow(item.path);
          selectedKey.value = [item.name as string];
          return;
        }
        // Eliminate external link side effects
        selectedKey.value = [item.name as string];
        const {hideInMenu, activeMenu} = item.meta as RouteMeta;
        if (route.name === item.name && !hideInMenu && !activeMenu) {
          return;
        }
        // Trigger router change
        router.push({
          name: item.name,
        });
      };
      const findMenuOpenKeys = (name: string) => {
        const result: string[] = [];
        let isFind = false;
        const backtrack = (
            item: RouteRecordRaw,
            keys: string[],
            target: string
        ) => {
          if (item.name === target) {
            isFind = true;
            result.push(...keys, item.name as string);
            return;
          }
          if (item.children?.length) {
            item.children.forEach((el) => {
              backtrack(el, [...keys], target);
            });
          }
        };
        menuTree.value.forEach((el: RouteRecordRaw) => {
          if (isFind) return; // Performance optimization
          backtrack(el, [el.name as string], name);
        });
        return result;
      };
      // 控制刷新后的菜单选择
      listenerRouteChange((newRoute) => {
        const {requiresAuth, activeMenu, hideInMenu} = newRoute.meta;
        if ((!hideInMenu || activeMenu)) {
          const menuOpenKeys = findMenuOpenKeys(
              (activeMenu || newRoute.name) as string
          );

          const keySet = new Set([...menuOpenKeys, ...openKeys.value]);
          openKeys.value = [...keySet];

          selectedKey.value = [
            activeMenu || menuOpenKeys[menuOpenKeys.length - 1],
          ];
        }
      }, true);
      const setCollapse = (val: boolean) => {
        if (appStore.device === 'desktop')
          appStore.updateSettings({menuCollapse: val});
      };

      const renderSubMenu = () => {
        function travel(_route: RouteRecordRaw[], nodes = []) {
          if (_route) {
            _route.forEach((element) => {
              // This is demo, modify nodes as needed
              const icon = element?.meta?.icon
                  ? () => h(compile(`<${element?.meta?.icon}/>`))
                  : null;
              const node =
                  element?.children && element?.children.length !== 0 ? (
                      <el-sub-menu
                          index={element?.name}
                          v-slots={{
                            icon,
                            title: () => h(compile(t(element?.meta?.locale || ''))),
                          }}
                      >
                        {travel(element?.children)}
                      </el-sub-menu>
                  ) : (
                      <el-menu-item
                          index={element?.name}
                          v-slots={{icon}}
                          onClick={() => goto(element)}
                      >
                        {t(element?.meta?.locale || '')}
                      </el-menu-item>
                  );
              nodes.push(node as never);
            });
          }
          return nodes;
        }

        return travel(menuTree.value);
      };

      return () => (
          <el-menu collapse={collapsed.value}
                   default-openeds={openKeys.value}
                   show-collapse-button={appStore.device !== 'mobile'}
                   auto-open={false}
                   default-active={selectedKey.value[0]}
                   auto-open-selected={true}
                   level-indent={34}
                   style={"height: 100%;position: fixed;width: " + appStore.menuWidth + "px"}
                   onCollapse={setCollapse}>
            {renderSubMenu()}
          </el-menu>
      );
    },
  });
</script>

<style lang="less" scoped>
  :deep(.arco-menu-inner) {
    .arco-menu-inline-header {
      display: flex;
      align-items: center;
    }

    .arco-icon {
      &:not(.arco-icon-down) {
        font-size: 18px;
      }
    }
  }
</style>
